#region Using Statements
using System;
using System.Collections.Generic;
using System.Linq;
using System.Media;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System.Diagnostics;
using System.IO;
#endregion using

namespace CakeRaid
{
    public class Game : Microsoft.Xna.Framework.Game
    {
        #region Attributes
        #region Graphic Stuff (Texture2D, SpriteFont, SpriteBatch, GraphicsDeviceManager)
        protected GraphicsDeviceManager graphics;
        protected SpriteBatch spriteBatch;
        protected SpriteFont largeFont, mediumFont, normalFont, smallFont;
        protected Dictionary<GameState, Texture2D> menuBackgrounds;
        protected TimeSpan pausedTime;
        protected GameTime animationTotalTime;
        
        public GameTime AnimationTime { get { return animationTotalTime; } }
        public Texture2D pixel, cursorTex, ammoTex, towersTex, trapsTex, menuiTex, ant, spider, beetle, ladybug, bee, wasp, dragonfly, boss,
            cakesTex, cakepieceTex, infoBoxTex, play_button, load_button, instruc_button, credits_button, exit_button, restart_button, enemy_effects;
        private List<Texture2D> levelBackgrounds;

        private int randomCakeVar;
        private Random cakeSelect;
        #endregion Graphic Stuff

        #region General Game Stuff (GameState, music stuff, Map, HUD)
        public enum GameState { Menu, Instructions, Credits, Game, Paused, GameOver_Lose, GameOver_Win }
        protected GameState gameState;
        protected bool /*debugOn,*/ musicOn, soundEffectsOn, drawCursor;
        protected float difficulty;
        protected int level, wave;
        private Map map; private Cake cake; private HUD hud;
        #endregion General Game Stuff

        #region Keyboard / Mouse Stuff (KeyboardState, MouseState, Button Dictionary)
        protected KeyboardState kbState, previouskbState;
        protected MouseState mouseState, previousMouseState;
        protected Rectangle mouseRect;
        protected Vector2 mousePoint;
        protected bool singlePress;
        protected Dictionary<GameState, List<Button>> buttons;
        #endregion Keyboard / Mouse Stuff

        #region Enemy Stuff (spawn stuff, enemies wave list / active list)
        private List<Path> paths;
        private List<Enemy> enemies;
        private List<List<Enemy>> prevWaves;
        private List<Queue<Enemy>> waves;
        protected List<Vector2> droppedCake;
        private Timer spawnTimer;
        #endregion Enemy Stuff

        #region Tower/Trap Stuff (Tower List, heldItem)
        protected GameObject heldItem, selectedItem, mouseOverItem;
        private List<Tower> towers;
        private List<Trap> traps;
        #endregion Tower/Trap Stuff

        #region Sound
        protected Song menuTheme, theme;
        protected SoundEffect splat, munch, towerPlace, towerShoot, acidBubble, flypaperPlacement, fireball;
        #endregion Sound
        #endregion Attributes

        #region Initialize
        public Game()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            graphics.PreferredBackBufferHeight = Var.TOTAL_HEIGHT;
            graphics.PreferredBackBufferWidth = Var.TOTAL_WIDTH;
            graphics.IsFullScreen = false;
            graphics.ApplyChanges();
            pixel = new Texture2D(GraphicsDevice, 1, 1); pixel.SetData<Color>(new Color[] { Color.White });
            gameState = GameState.Menu;

            singlePress = false; /*debugOn = false;*/ musicOn = true; soundEffectsOn = true;

            base.Initialize();
        }

        /// <summary>
        /// Objects that use things such as Textures / SpriteBatches
        /// that need to be made after LoadContent go here.
        /// </summary>
        protected void InitializeAfterLoadContent()
        {
            // Most of these are in NewGame()
            buttons = new Dictionary<GameState, List<Button>>
            {
                { GameState.Menu,
                    new List<Button> {
                        new Button(null, new Vector2(35, 230), 304, 139, 0, Color.White, spriteBatch, null, null),//play button
                        new Button(null, new Vector2(35, 380), 658, 104, 0, Color.White, spriteBatch, null, null),//instructions button
                        new Button(null, new Vector2(35, 495), 459, 122, 0, Color.White, spriteBatch, null, null),//credits button
                        new Button(null, new Vector2(0, 0), 0, 0, 0, Color.White, spriteBatch, null, null),//load button
                        new Button(null, new Vector2(Var.TOTAL_WIDTH - 226, 0), 226, 122, 0, Color.White, spriteBatch, null, null)//exit button
                    }
                },
                { GameState.Paused,
                    new List<Button> {
                        new Button(Var.BLANK_TEX, new Vector2(25), 300, 300, 1, Color.DarkOrange, spriteBatch, new TextObject("", Vector2.Zero, mediumFont, Color.GhostWhite, spriteBatch), null)
                    }
                },
                { GameState.GameOver_Win,
                    new List<Button> {
                        new Button(Var.BLANK_TEX, new Vector2(250, Var.TOTAL_HEIGHT - 200), 226, 122, 2, Color.FromNonPremultiplied(136, 0, 21, 255), spriteBatch, new TextObject("", Vector2.Zero, largeFont, Color.FromNonPremultiplied(136, 0, 21, 255), spriteBatch), new ButtonEvent(GoToMenu))
                    }
                },
                { GameState.GameOver_Lose,
                    new List<Button> {
                        new Button(Var.BLANK_TEX, new Vector2(250, Var.TOTAL_HEIGHT - 200), 226, 122, 2, Color.FromNonPremultiplied(136, 0, 21, 255), spriteBatch, new TextObject("", Vector2.Zero, largeFont, Color.FromNonPremultiplied(136, 0, 21, 255), spriteBatch), new ButtonEvent(GoToMenu)),
                        new Button(Var.BLANK_TEX, new Vector2(800, Var.TOTAL_HEIGHT - 200), 392, 112, 2, Color.FromNonPremultiplied(136, 0, 21, 255), spriteBatch, new TextObject("", Vector2.Zero, largeFont, Color.FromNonPremultiplied(136, 0, 21, 255), spriteBatch), new ButtonEvent(RestartGame))
                    }
                }
            };
            buttons[GameState.Paused][0].Color = Color.Black;
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            Var.BLANK_TEX = this.Content.Load<Texture2D>("Blank");
            cursorTex = this.Content.Load<Texture2D>("Cursor");

            #region Menu
            menuBackgrounds = new Dictionary<GameState, Texture2D>
            {
                { GameState.Menu, this.Content.Load<Texture2D>("Menu/MainMenu") },
                { GameState.Instructions, this.Content.Load<Texture2D>("Menu/Instructions") },
                { GameState.Credits, this.Content.Load<Texture2D>("Menu/Credits") },
                { GameState.GameOver_Win, this.Content.Load<Texture2D>("Menu/Win") },
                { GameState.GameOver_Lose, this.Content.Load<Texture2D>("Menu/Lose") }
            };

            levelBackgrounds = new List<Texture2D> { this.Content.Load<Texture2D>("Menu/gameScreen"), this.Content.Load<Texture2D>("Menu/gameScreen2"), this.Content.Load<Texture2D>("Menu/gameScreen3"), this.Content.Load<Texture2D>("Menu/gameScreenBoss") };

            play_button = this.Content.Load<Texture2D>("Menu/play_button");
            load_button = this.Content.Load<Texture2D>("Menu/play_button");
            instruc_button = this.Content.Load<Texture2D>("Menu/instructions_button");
            credits_button = this.Content.Load<Texture2D>("Menu/credits_button");
            exit_button = this.Content.Load<Texture2D>("Menu/exit_button");
            restart_button = this.Content.Load<Texture2D>("Menu/restart_button");
            #endregion Menu

            #region HUD
            infoBoxTex = this.Content.Load<Texture2D>("HUD/InfoBox");
            menuiTex = this.Content.Load<Texture2D>("HUD/ss_menu_items");
            #endregion HUD

            #region Spritefonts
            largeFont = this.Content.Load<SpriteFont>("Spritefonts/Large");
            mediumFont = this.Content.Load<SpriteFont>("Spritefonts/Medium");
            normalFont = this.Content.Load<SpriteFont>("Spritefonts/Normal");
            smallFont = this.Content.Load<SpriteFont>("Spritefonts/Small");
            #endregion Spritefonts

            #region Sprites
            //Enemy sprite sheets
            ant = this.Content.Load<Texture2D>("Sprites/ss_ant");
            spider = this.Content.Load<Texture2D>("Sprites/ss_spider");
            beetle = this.Content.Load<Texture2D>("Sprites/ss_beetle");
            bee = this.Content.Load<Texture2D>("Sprites/ss_bee");
            wasp = this.Content.Load<Texture2D>("Sprites/ss_wasp");
            dragonfly = this.Content.Load<Texture2D>("Sprites/ss_dragonfly");
            ladybug = this.Content.Load<Texture2D>("Sprites/ss_ladybug");
            boss = this.Content.Load<Texture2D>("Sprites/ss_boss");

            //Enemy healing and shock effects
            enemy_effects = this.Content.Load<Texture2D>("Sprites/ss_enemy_effects");

            //Cake sprite sheet and cake piece sprite
            cakesTex = this.Content.Load<Texture2D>("Sprites/ss_cake_states");
            cakepieceTex = this.Content.Load<Texture2D>("Sprites/cakepiece");

            //Tower textures
            towersTex = this.Content.Load<Texture2D>("Sprites/ss_tower_states");

            //Trap textures
            trapsTex = this.Content.Load<Texture2D>("Sprites/ss_trap");

            //Bullet, fireball textures
            ammoTex = this.Content.Load<Texture2D>("Sprites/ss_ammo");
            #endregion Sprites

            #region Sound
            //music
            menuTheme = this.Content.Load<Song>("Sound/LetThemEat");
            theme = this.Content.Load<Song>("Sound/Music");

            //enemy sounds
            splat = this.Content.Load<SoundEffect>("Sound/BugDeath");
            munch = this.Content.Load<SoundEffect>("Sound/CakeMunch");

            //tower sounds
            towerPlace = this.Content.Load<SoundEffect>("Sound/TowerPlacement");
            towerShoot = this.Content.Load<SoundEffect>("Sound/towershoot");
            fireball = this.Content.Load<SoundEffect>("Sound/Fireball");

            //trap sounds
            acidBubble = this.Content.Load<SoundEffect>("Sound/AcidBubbling");
            flypaperPlacement = this.Content.Load<SoundEffect>("Sound/FlypaperPlacement");
            #endregion Sound

            InitializeAfterLoadContent();
        }
        #endregion Initialize

        #region Update
        protected override void Update(GameTime gameTime)
        {
            #region Kb/MouseState
            singlePress = false;

            //Keyboard
            previouskbState = kbState;
            kbState = Keyboard.GetState();

            previousMouseState = mouseState;
            mouseState = Mouse.GetState();

            mouseRect = new Rectangle(mouseState.X, mouseState.Y, 1, 1);
            mousePoint = new Vector2(mouseState.X, mouseState.Y);
            #endregion Kb/MouseState

            animationTotalTime = new GameTime(gameTime.TotalGameTime - pausedTime, TimeSpan.Zero);

            switch (gameState)
            {
                #region GameState.Game
                case GameState.Game:

                    #region Update
                    if (!musicOn && MediaPlayer.State == MediaState.Playing)
                        MediaPlayer.Stop();
                    else if (musicOn && MediaPlayer.State != MediaState.Playing)
                        MediaPlayer.Play(theme);

                    QuickKeys();

                    if (heldItem != null)
                    {
                        heldItem.Center = mousePoint;
                        drawCursor = false;
                    }
                    else
                    {
                        drawCursor = true;
                    }

                    NextWave(); // If it can begins next wave

                    for (int i = 0; i < enemies.Count; i++)
                    {
                        enemies[i].Update(animationTotalTime, enemies, droppedCake);

                        #region Update Towers
                        for (int j = 0; j < towers.Count; j++)
                        {
                            towers[j].Update(gameTime);
                            towers[j].UpdateEnemiesInRange(enemies);
                            towers[j].Activate();

                            towers[j].CheckBulletCollision(enemies[i]);

                            towers.Remove(towers[j].RemoveIfCan());
                        }
                        #endregion Update Towers

                        #region Update Traps
                        for (int j = 0; j < traps.Count; j++)
                        {
                            traps[j].Update(gameTime);
                                
                            if ((enemies[i].Behavior != Enemy.BehaviorState.Death) && (enemies[i].Behavior != Enemy.BehaviorState.Spawn))
                            {
                                traps[j].Activate(enemies[i].Center);

                                #region Applied trap effects
                                if (traps[j].Type == Var.TrapType.Acid && traps[j].CanHit)
                                {
                                    if (musicOn)
                                        acidBubble.Play();
                                    enemies[i].Hit(traps[j].Damage);
                                    //add armor reduction?
                                }
                                else if (traps[j].Type == Var.TrapType.Flypaper && traps[j].CanHit)
                                {
                                    enemies[i].Slow();
                                }
                                else if (traps[j].Type == Var.TrapType.Snare && traps[j].CanHit)
                                {
                                    //take cake from enemy and update remaining count
                                    if (enemies[i].HasCake)
                                    {
                                        enemies[i].HasCake = false;
                                        cake.takenCakeCount--;
                                        cake.remainingCakeCount++;

                                        //only takes wear damage when cake is found and taken
                                        traps[j].healthBar.Show(gameTime);
                                        traps[j].CurrentHealth--;
                                    }
                                }
                                else if (traps[j].Type == Var.TrapType.Zapper && traps[j].CanHit)
                                {
                                    enemies[i].Hit(traps[j].Damage);
                                    enemies[i].Shock();
                                    traps[j].ResetEventTimer();
                                }

                                traps[j].CanHit = false;
                                #endregion Applied trap effects
                            }

                            traps.Remove(traps[j].RemoveIfCan());
                        }
                        #endregion Update Traps

                        if (enemies[i].IsActive)
                        {
                            if ((enemies[i] is Enemy_Ant || enemies[i] is Enemy_Beetle || enemies[i] is Enemy_Spider) && !enemies[i].Status_effects[3])
                            {
                                //check cake adjacency
                                if (!enemies[i].HasCake && cake.remainingCakeCount > 0)
                                {
                                    enemies[i].FindCake();

                                    if (enemies[i].AdjacentToCake)
                                    {
                                        if (musicOn)
                                            munch.Play();
                                        enemies[i].HasCake = true;
                                        cake.takenCakeCount++;
                                        cake.remainingCakeCount--;
                                    }
                                }

                                //check dropped cake
                                for (int j = 0; j < droppedCake.Count; j++)
                                {
                                    if (!enemies[i].HasCake && enemies[i].Rectangle.Intersects(new Rectangle((int)droppedCake[j].X, (int)droppedCake[j].Y, 10, 10)))
                                    {
                                        if (musicOn)
                                            munch.Play();
                                        enemies[i].HasCake = true;
                                        droppedCake.RemoveAt(j);
                                    }
                                }
                            }
                            else if ((enemies[i] is Enemy_Bee || enemies[i] is Enemy_Wasp || enemies[i] is Enemy_SpiderBoss) || enemies[i].Status_effects[3])
                            {
                                if (enemies[i].FocusedTower == null)
                                {
                                    enemies[i].RefreshFocusedTower();
                                }
                                else
                                {
                                    //if following path and not in range of the tower, switch to moving towards the tower
                                    //and attack when within range
                                    if (enemies[i].Behavior == Enemy.BehaviorState.FollowPath)
                                    {
                                        enemies[i].Behavior = Enemy.BehaviorState.MoveToTower;
                                    }
                                    //if in range of tower, switch to attacking
                                    if (enemies[i].Behavior == Enemy.BehaviorState.MoveToTower)
                                    {
                                        if (enemies[i].AttackRange >= Vector2.Distance(enemies[i].FocusedTower.Center, enemies[i].Center))
                                        {
                                            enemies[i].Behavior = Enemy.BehaviorState.AttackTower;
                                        }
                                    }
                                    if (enemies[i].Behavior == Enemy.BehaviorState.AttackTower)
                                    {
                                        //Enemy damages tower
                                        if (enemies[i].FocusedTower.IsActive)
                                        {
                                            for(int j = 0; j < towers.Count; j++)
                                            {
                                                if (towers[j].Center.X == enemies[i].FocusedTower.Center.X && towers[j].Center.Y == enemies[i].FocusedTower.Center.Y)
                                                {
                                                    towers[j].Hit(enemies[i].Damage);
                                                    if (towers[j].CurrentHealth <= 0)
                                                    {
                                                        enemies[i].Behavior = Enemy.BehaviorState.MoveFromTower;
                                                    }
                                                }
                                            }
                                        }
                                        else
                                        {
                                            enemies[i].FocusedTower = null;
                                        }
                                    }
                                }
                            }
                        }
                        else
                        {
                            //if enemies die with cake, add a cake to the dropped list
                            if (enemies[i].HasCake && !(enemies[i].Path.GetTile(enemies[i].CurrentTile) == enemies[i].Path.End))
                            {
                                if (enemies[i] is Enemy_Ant || enemies[i] is Enemy_Spider || enemies[i] is Enemy_Beetle)
                                {
                                    droppedCake.Add(enemies[i].Point);
                                }
                            }

                            //if enemies die, remove the enemy and play dying sound effect
                            enemies.RemoveAt(i);
                            i--;
                            if (musicOn)
                                splat.Play();
                        }
                    }

                    hud.Update(animationTotalTime);
                    #endregion Update

                    #region Mouse Over

                    #region Menu Display (note: clicking on it is with other click stuff below)
                    if (!hud.MenuButton.Focused && mouseRect.Intersects(hud.MenuButton.Rectangle))
                    {
                        hud.StartMenuOpening(animationTotalTime);
                    }
                    else if (hud.MenuButton.Focused)
                    {
                        // This rectangle is the rectangle from top of menu bttn to bottom of last menu option.
                        if (mouseRect.Intersects(new Rectangle(hud.MenuButton.X, hud.MenuButton.Y, hud.MenuButton.Width, (hud.MenuButton.ChildButtons.Last().Y + hud.MenuButton.ChildButtons.Last().Height) - hud.MenuButton.Y)))
                        {
                            hud.MenuButton.Focused = true;
                            drawCursor = true;
                        }
                        else
                            hud.MenuButton.Focused = false;
                    }
                    #endregion Menu Display

                    #region Selection Bar Name/Price MouseOver
                    foreach (GameObject itm in hud.SelectionBar)
                    {
                        if (itm.Rectangle.Intersects(mouseRect))
                        {
                            hud.CostWindow.IsActive = true;
                            drawCursor = true;
                            string name = "";
                            int cost = 0;
                            string desc = "";
                            if (itm is Tower)
                            {
                                Tower tower = (Tower)itm;
                                name = Var.towerNames[tower.Type];
                                cost = tower.Cost;
                                if (tower is Tower_Rad)
                                    desc = "Shoots enemies!";
                                else if (tower is Tower_Shock)
                                    desc = "Shocking tower!";
                                else if (tower is Tower_Fire)
                                    desc = "Shoots fireballs at enemies!";
                                else if (tower is Tower_Light)
                                    desc = "Attracts enemies!";
                            }
                            else if (itm is Trap)
                            {
                                Trap trap = (Trap)itm;
                                name = Var.trapNames[trap.Type];
                                cost = trap.Cost;
                                if (trap is Trap_Acid)
                                    desc = "Damages enemies slightly!";
                                else if (trap is Trap_Flypaper)
                                    desc = "Slows enemies!";
                                else if (trap is Trap_Zapper)
                                    desc = "Damages enemies greatly! Click to activate.";
                                else if (trap is Trap_Snare)
                                    desc = "Retrieves cake from enemies!";
                            }

                            hud.CostWindow.TextObjects[0].Message = name;
                            hud.CostWindow.TextObjects[1].Message = "$" + cost;
                            hud.CostWindow.TextObjects[2].Message = desc;

                            int width = hud.CostWindow.TextObjects[0].Width + 10;
                            if (hud.CostWindow.TextObjects[2].Width + 10 > width)
                                width = hud.CostWindow.TextObjects[2].Width + 10;

                            hud.CostWindow.Width = width;
                            hud.CostWindow.Center = new Vector2(itm.Center.X, hud.CostWindow.Center.Y);
                            foreach (TextObject to in hud.CostWindow.TextObjects)
                            {
                                to.Center = new Vector2(itm.Center.X, to.Center.Y);
                            }

                            break;
                        }
                        else
                        {
                            hud.CostWindow.IsActive = false;
                        }
                    }
                    #endregion Selection Bar Name/Price MouseOver

                    #region Something Already Placed
                    List<GameObject> gos = new List<GameObject>();
                    gos.AddRange(towers); gos.AddRange(traps);
                    foreach (GameObject itm in gos)
                    {
                        if (itm.Rectangle.Intersects(mouseRect) && itm.IsActive)
                        {
                            hud.InfoWindow.IsActive = true;
                            mouseOverItem = itm;
                            string message = "-";
                            if (itm is Tower)
                            {
                                Tower mouseOverTower = (Tower)mouseOverItem;
                                if (mouseOverTower is Tower_Shock && mouseOverTower.UpgradeLevel < 3)
                                    message = "Value: " + mouseOverTower.Cost + "\n[S]ale Price: " + mouseOverTower.SellCost() + "\nUpgrade Level: " + mouseOverTower.UpgradeLevel + "\n[U]pgrade Cost: " + mouseOverTower.Cost;
                                else if (mouseOverTower is Tower_Shock && mouseOverTower.UpgradeLevel >= 3)
                                    message = "Value: " + mouseOverTower.Cost + "\n[S]ale Price: " + mouseOverTower.SellCost() + "\nUpgrade Level: " + mouseOverTower.UpgradeLevel;
                                else if (!(mouseOverTower is Tower_Shock) && mouseOverTower.UpgradeLevel >= 3)
                                    message = "Value: " + mouseOverTower.Cost + "\n[S]ale Price: " + mouseOverTower.SellCost() + "\nUpgrade Level: " + mouseOverTower.UpgradeLevel + "\n[A]ttack Mode: " + mouseOverTower.AttackType;
                                else
                                    message = "Value: " + mouseOverTower.Cost + "\n[S]ale Price: " + mouseOverTower.SellCost() + "\nUpgrade Level: " + mouseOverTower.UpgradeLevel + "\n[U]pgrade Cost: " + mouseOverTower.Cost + "\n[A]ttack Mode: " + mouseOverTower.AttackType;
                            }
                            else if (itm is Trap)
                            {
                                Trap mouseOverTrap = (Trap)mouseOverItem;
                                message = "Value: " + mouseOverTrap.Cost;
                            }

                            hud.InfoWindow.TextObjects[0].Message = message;

                            hud.InfoWindow.Width = hud.InfoWindow.TextObjects[0].Width + 10;
                            hud.InfoWindow.CenterX = (int)itm.Center.X;

                            hud.InfoWindow.Height = hud.InfoWindow.TextObjects[0].Height + 10;
                            hud.InfoWindow.Y = (int)itm.Y - hud.InfoWindow.Height - 5;

                            hud.InfoWindow.TextObjects[0].Center = hud.InfoWindow.Center;

                            break;
                        }
                        else
                        {
                            hud.InfoWindow.IsActive = false;
                        }
                    }
                    #endregion Something Already Placed

                    #endregion Mouse Over

                    #region If Mouse Clicked
                    if (CheckIfClicked(Var.GAME_AREA))
                    {
                        singlePress = false;

                        #region Menu List Buttons
                        ClickGameDropDownMenuItemsIfCan();
                        #endregion Menu List Buttons

                        #region Select Tower / trap from Selection Bar
                        foreach (GameObject itm in hud.SelectionBar)
                        {
                            if (CheckIfClicked(itm.Rectangle))
                            {
                                if (itm is Tower)
                                {
                                    heldItem = LoadTower(((Tower)itm).Type);
                                    heldItem.Point = mousePoint;
                                }
                                else if (itm is Trap)
                                {
                                    heldItem = LoadTrap(((Trap)itm).Type);
                                    heldItem.Point = mousePoint;
                                }
                            }
                        }
                        #endregion Select Tower / trap from Selection Bar

                        #region Click Something (normally)
                        if (heldItem == null)
                        {
                            foreach (Tower tower in towers)
                            {
                                if (CheckIfClicked(tower.Rectangle))
                                {
                                    selectedItem = tower;
                                    break;
                                }
                            }

                            if (!singlePress)
                            {
                                foreach (Trap trap in traps)
                                {
                                    if (CheckIfClicked(trap.Rectangle))
                                    {
                                        selectedItem = trap;
                                        if (selectedItem is Trap_Zapper)
                                        {
                                            ((Trap_Zapper)selectedItem).IsClicked = true;
                                        }
                                        break;
                                    }
                                }
                            }

                            if (!singlePress)
                                selectedItem = null;
                        }
                        #endregion Click Something (normally)

                        #region Place Something
                        else
                        {
                            foreach (Tile tile in map.Tiles)
                            {
                                if (CheckIfClicked(tile.Rectangle))
                                {
                                    if (tile is Tile_Tower)
                                    {
                                        if ((heldItem != null) && (heldItem is Tower) && (tile.OccupiedBy == null) && hud.CanSpendMoney(((Tower)heldItem).Cost))
                                        {
                                            hud.Money -= ((Tower)heldItem).Cost;
                                            ((Tower)heldItem).Place((Tile_Tower)tile);
                                            towers.Add(((Tower)heldItem));
                                            heldItem = LoadTower(((Tower)heldItem).Type);
                                            heldItem.Point = mousePoint;
                                            if (musicOn)
                                                towerPlace.Play();
                                        }
                                    }
                                    else if (tile is Tile_Path)
                                    {
                                        if ((heldItem != null) && (heldItem is Trap) && (tile.OccupiedBy == null) && hud.CanSpendMoney(((Trap)heldItem).Cost))
                                        {
                                            hud.Money -= ((Trap)heldItem).Cost;
                                            ((Trap)heldItem).Place((Tile_Path)tile);
                                            traps.Add(((Trap)heldItem));
                                            heldItem = LoadTrap(((Trap)heldItem).Type);
                                            heldItem.Point = mousePoint;
                                            if (heldItem is Trap_Flypaper && musicOn)
                                                flypaperPlacement.Play();
                                        }
                                    }
                                    break;
                                }
                            }
                        }
                        #endregion Place Something
                    }

                    #region RIGHT Click
                    else if ((mouseState.RightButton == ButtonState.Released) && (previousMouseState.RightButton == ButtonState.Pressed))
                    {
                        if (heldItem != null)
                            heldItem = null;
                        else
                            selectedItem = null;
                    }
                    #endregion RIGHT Click

                    #endregion If Mouse Clicked

                    if (cake.CurrentHealth <= 0)
                    {
                        gameState = GameState.GameOver_Lose;
                    }

                    break;
                #endregion GameState.Game

                #region Everything else

                #region Paused
                case GameState.Paused:
                    //maybe facilitate gameTime in hud
                    pausedTime += gameTime.ElapsedGameTime;

                    // Allows Menu items to be interactable in pause
                    hud.Update(gameTime);
                    if (!hud.MenuButton.Focused)
                        hud.StartMenuOpening(gameTime);

                    ClickGameDropDownMenuItemsIfCan();

                    if (SingleKeyPress(Keys.P))
                    {
                        gameState = GameState.Game;
                    }
                    /*else if (CheckIfClicked(buttons[GameState.Paused][0].Rectangle))
                    {
                        debugOn = !debugOn;
                    }*/
                    break;
                #endregion Paused

                #region Menu
                case GameState.Menu:
                    //MediaPlayer.Stop();
                    if (MediaPlayer.State != MediaState.Playing)
                        MediaPlayer.Play(menuTheme);

                    if (CheckIfClicked(buttons[gameState][0].Rectangle))
                    {
                        if(MediaPlayer.State == MediaState.Playing)
                            MediaPlayer.Stop();
                        NewGame();
                        gameState = GameState.Game;
                    }
                    else if (CheckIfClicked(buttons[gameState][1].Rectangle))
                    {
                        gameState = GameState.Instructions;
                    }
                    else if (CheckIfClicked(buttons[gameState][2].Rectangle))
                    {
                        gameState = GameState.Credits;
                    }
                    else if (CheckIfClicked(buttons[gameState][3].Rectangle) && CheckForSave())
                    {
                        ContinueGame();
                        gameState = GameState.Game;
                    }
                    else if (CheckIfClicked(buttons[gameState][4].Rectangle) || SingleKeyPress(Keys.Escape))
                    {
                        Environment.Exit(0);
                    }
                    break;
                #endregion Menu

                case GameState.Instructions:
                    if (mouseState.RightButton == ButtonState.Pressed)
                        gameState = GameState.Menu;
                    break;
                case GameState.Credits:
                    if (mouseState.RightButton == ButtonState.Pressed)
                        gameState = GameState.Menu;
                    break;

                #region GameOver (Win/Lose)
                case GameState.GameOver_Win:
                case GameState.GameOver_Lose:
                    foreach (Button bttn in buttons[gameState])
                    {
                        bttn.Resize = Vector2.One;

                        if (bttn.Intersects(mouseRect))
                        {
                            bttn.Resize = new Vector2(1.025f);
                            if (CheckIfClicked(bttn.Rectangle))
                                bttn.Click();
                        }
                    }
                    break;
                #endregion GameOver (Win/Lose)

                #endregion Everything else
            }
            base.Update(gameTime);
        }
        #endregion Update 

        #region Draw
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.DarkGreen);
            spriteBatch.Begin();
            switch (gameState)
            {
                #region GameState.Game
                case GameState.Game:
                case GameState.Paused:

                    #region Level Backgrounds
                    switch (level)
                    {
                        case 0:
                            spriteBatch.Draw(levelBackgrounds[0], Var.SCREEN_SIZE, Color.White);
                            break;
                        case 1:
                            spriteBatch.Draw(levelBackgrounds[1], Var.SCREEN_SIZE, Color.White);
                            break;
                        case 2:
                            spriteBatch.Draw(levelBackgrounds[2], Var.SCREEN_SIZE, Color.White);
                            break;
                        case 3:
                            spriteBatch.Draw(levelBackgrounds[3], Var.SCREEN_SIZE, Color.White);
                            break;
                    }
                    #endregion Level Backgrounds

                    #region Cake
                    //Draws cake randomly per level and adjusts for damage
                    switch(randomCakeVar)
                    {
                        case 0:
                            #region Draw first cake
                            switch (cake.remainingCakeCount)
                            {
                                case 5:
                                    cake.Draw(0, 0);
                                    break;
                                case 4:
                                    cake.Draw(1, 0);
                                    break;
                                case 3:
                                    cake.Draw(2, 0);
                                    break;
                                case 2:
                                    cake.Draw(3, 0);
                                    break;
                                case 1:
                                    cake.Draw(4, 0);
                                    break;
                            }
                            #endregion Draw first cake
                            break;
                        case 1:
                            #region Draw second cake
                            switch (cake.remainingCakeCount)
                            {
                                case 5:
                                    cake.Draw(0, 1);
                                    break;
                                case 4:
                                    cake.Draw(1, 1);
                                    break;
                                case 3:
                                    cake.Draw(2, 1);
                                    break;
                                case 2:
                                    cake.Draw(3, 1);
                                    break;
                                case 1:
                                    cake.Draw(4, 1);
                                    break;
                            }
                            #endregion Draw second cake
                            break;
                        case 2:
                            #region Draw third cake
                            switch (cake.remainingCakeCount)
                            {
                                case 5:
                                    cake.Draw(0, 2);
                                    break;
                                case 4:
                                    cake.Draw(1, 2);
                                    break;
                                case 3:
                                    cake.Draw(2, 2);
                                    break;
                                case 2:
                                    cake.Draw(3, 2);
                                    break;
                                case 1:
                                    cake.Draw(4, 2);
                                    break;
                            }
                            #endregion Draw third cake
                            break;
                        case 3:
                            #region Draw fourth cake
                            switch (cake.remainingCakeCount)
                            {
                                case 5:
                                    cake.Draw(0, 3);
                                    break;
                                case 4:
                                    cake.Draw(1, 3);
                                    break;
                                case 3:
                                    cake.Draw(2, 3);
                                    break;
                                case 2:
                                    cake.Draw(3, 3);
                                    break;
                                case 1:
                                    cake.Draw(4, 3);
                                    break;
                            }
                            #endregion Draw fourth cake
                            break;
                        case 4:
                            #region Draw fifth cake
                            switch (cake.remainingCakeCount)
                            {
                                case 5:
                                    cake.Draw(0, 4);
                                    break;
                                case 4:
                                    cake.Draw(1, 4);
                                    break;
                                case 3:
                                    cake.Draw(2, 4);
                                    break;
                                case 2:
                                    cake.Draw(3, 4);
                                    break;
                                case 1:
                                    cake.Draw(4, 4);
                                    break;
                            }
                            #endregion Draw fifth cake
                            break;
                    }
                    #endregion Cake 

                    #region Towers
                    Tower mouseOverTower = null;
                    foreach (Tower tower in towers)
                    {
                        tower.Draw(gameTime);

                        if (mouseRect.Intersects(tower.Rectangle))
                            mouseOverTower = tower;
                    }
                    if ((mouseOverTower != null) && mouseOverTower.IsActive)
                    {
                        // InfoWindow changed in MouseOver part of Update()
                        DrawCircle(mouseOverTower.Center, mouseOverTower.FireRadius, 64, Color.Red);
                    }
                    if ((selectedItem is Tower) && (selectedItem != mouseOverTower) && selectedItem.IsActive)
                    {
                        DrawCircle(selectedItem.Center, ((Tower)selectedItem).FireRadius, 64, Color.Red);
                        ImageObject.DrawRectangleOutline(((Tower)selectedItem).OccupiedTile.Rectangle, 3, Color.Blue, Var.BLANK_TEX, spriteBatch);
                    }
                    #endregion Towers

                    #region Traps
                    Trap mouseOverTrap = null;
                    foreach (Trap trap in traps)
                    {
                        trap.Draw(gameTime);

                        if (mouseRect.Intersects(trap.Rectangle))
                            mouseOverTrap = trap;
                    }
                    if ((selectedItem is Trap) && (selectedItem != mouseOverTrap) && selectedItem.IsActive)
                    {
                        ImageObject.DrawRectangleOutline(((Trap)selectedItem).OccupiedTile.Rectangle, 3, Color.Green, Var.BLANK_TEX, spriteBatch);
                    }
                    #endregion Traps

                    droppedCake.ForEach(dropped => spriteBatch.Draw(cakepieceTex, new Rectangle(((int)dropped.X), ((int)dropped.Y), 15, 15), Color.White));
                    enemies.ForEach(enemy => enemy.Draw(gameTime));

                    if (heldItem != null)
                    {
                        heldItem.Draw(0, 0);
                        foreach (Tile tile in map.Tiles)
                        {
                            if (mouseRect.Intersects(tile.Rectangle))
                            {
                                if ((heldItem is Tower) && (tile is Tile_Tower) && !(tile.OccupiedBy is Cake))
                                {
                                    ImageObject.DrawRectangleOutline(tile.Rectangle, 2, Color.Blue, Var.BLANK_TEX, spriteBatch);
                                    DrawCircle(tile.Center, ((Tower)heldItem).FireRadius, 64, Color.Red);
                                }
                                else if ((heldItem is Trap) && (tile is Tile_Path))
                                    ImageObject.DrawRectangleOutline(tile.Rectangle, 2, Color.Green, Var.BLANK_TEX, spriteBatch);
                            }
                        }
                    }

                    #region Debug Stuff
                    /*if (debugOn)
                    {
                        towers.ForEach(tower => DrawCircle(tower.Center, tower.FireRadius, 25, Color.Red));
                        enemies.ForEach(enemy => enemy.DrawRectangleOutline(1, Color.DarkCyan, blankTex));
                    }*/
                    #endregion Debug Stuff

                    hud.Draw(0, 0);

                    // break; is in Pause.
                #endregion GameState.Game

                #region Everything else

                #region GameState.Paused
                    // Draws everything in GameState.Game (from above) plus this
                    if (gameState == GameState.Paused)
                    {
                        spriteBatch.Draw(Var.BLANK_TEX, Var.SCREEN_SIZE, Var.PAUSE_GRAY);
                        hud.DrawDropDownMenu(0, 0);
                        spriteBatch.DrawString(largeFont, "Press [P] or click \'Pause\'", new Vector2(Var.GAME_AREA.X + (Var.GAME_AREA.Width - largeFont.MeasureString("Press [P] or click \'Pause\'").X) / 2, Var.TOTAL_HEIGHT - largeFont.MeasureString("-").Y - 10), Color.YellowGreen);

                        #region Debug
                        /*if (debugOn)
                        {
                            if (mouseRect.Intersects(buttons[gameState][0].Rectangle))
                            {
                                buttons[gameState][0].Message.Message = "Fine, turn me off.\n\"You can't\nHANDLE\nthe TRUTH!\"";
                                buttons[gameState][0].CenterText();
                                buttons[gameState][0].Draw();
                            }
                            else
                            {
                                buttons[gameState][0].Message.Message = "Cheater.";
                                buttons[gameState][0].CenterText();
                                buttons[gameState][0].Draw();
                            }
                        }
                        else
                        {
                            if (mouseRect.Intersects(buttons[gameState][0].Rectangle))
                            {
                                buttons[gameState][0].Message.Message = "Turn on Debugging.\nYou know you wanna.";
                                buttons[gameState][0].CenterText();
                                buttons[gameState][0].Draw();
                            }
                        }*/
                        #endregion Debug
                    }
                    break;

                #endregion GameState.Paused

                case GameState.Menu:
                    spriteBatch.Draw(menuBackgrounds[gameState], Var.SCREEN_SIZE, Color.White);

                    spriteBatch.Draw(play_button, buttons[gameState][0].Rectangle, Color.White);
                    spriteBatch.Draw(instruc_button, buttons[gameState][1].Rectangle, Color.White);
                    spriteBatch.Draw(credits_button, buttons[gameState][2].Rectangle, Color.White);
                    spriteBatch.Draw(Var.BLANK_TEX, buttons[gameState][3].Rectangle, Color.White);
                    spriteBatch.Draw(exit_button, buttons[gameState][4].Rectangle, Color.White);
                    foreach (Button bttn in buttons[gameState])
                    {
                        if (mouseRect.Intersects(bttn.Rectangle))
                            bttn.DrawRectangleOutline(5, Color.FromNonPremultiplied(254, 165, 255, 255), Var.BLANK_TEX);
                    }
                    break;
                case GameState.Instructions:
                    spriteBatch.Draw(menuBackgrounds[gameState], Var.SCREEN_SIZE, Color.White);
                    spriteBatch.DrawString(mediumFont, "Right click to return", new Vector2(15, Var.TOTAL_HEIGHT - mediumFont.MeasureString("-").Y - 10), Color.Brown);
                    break;
                case GameState.Credits:
                    spriteBatch.Draw(menuBackgrounds[gameState], Var.SCREEN_SIZE, Color.White);
                    spriteBatch.DrawString(mediumFont, "Right click to return", new Vector2(15, Var.TOTAL_HEIGHT - mediumFont.MeasureString("-").Y - 10), Color.Brown);
                    break;
                case GameState.GameOver_Win:
                    spriteBatch.Draw(menuBackgrounds[gameState], Var.SCREEN_SIZE, Color.White);
                    spriteBatch.Draw(exit_button, buttons[gameState][0].Rectangle, Color.White);
                    buttons[gameState].ForEach(bttn => ImageObject.DrawRectangleOutline(bttn.Resized(), bttn.outLineThickness, Color.FromNonPremultiplied(bttn.outlineColor.R, bttn.outlineColor.G, bttn.outlineColor.B, (byte)(bttn.outlineColor.A * (bttn.Transparency / 100))), Var.BLANK_TEX, spriteBatch));
                    break;
                case GameState.GameOver_Lose:
                    spriteBatch.Draw(menuBackgrounds[gameState], Var.SCREEN_SIZE, Color.White);
                    spriteBatch.Draw(exit_button, buttons[gameState][0].Rectangle, Color.White);
                    spriteBatch.Draw(restart_button, buttons[gameState][1].Rectangle, Color.White);
                    buttons[gameState].ForEach(bttn => ImageObject.DrawRectangleOutline(bttn.Resized(), bttn.outLineThickness, Color.FromNonPremultiplied(bttn.outlineColor.R, bttn.outlineColor.G, bttn.outlineColor.B, (byte)(bttn.outlineColor.A * (bttn.Transparency / 100))), Var.BLANK_TEX, spriteBatch));
                    break;
                #endregion Everything else
            }

            if ((drawCursor && (gameState == GameState.Game)) || (gameState != GameState.Game))
                spriteBatch.Draw(cursorTex, new Rectangle(mouseRect.X, mouseRect.Y, 25, 25), Color.White);

            spriteBatch.End();
            base.Draw(gameTime);
        }
        #endregion Draw

        #region QuickKeys / Mouse / Keyboard Stuff

        #region Quick Keys
        /// <summary> Called in GameState.Game (NOT GameState.Paused)</summary>
        public void QuickKeys()
        {
            if (SingleKeyPress(Keys.M))
            {
                musicOn = soundEffectsOn = !musicOn;
            }
            if (SingleKeyPress(Keys.P))
            {
                gameState = GameState.Paused;
            }
            if (SingleKeyPress(Keys.R))
            {
                ContinueGame();
            }
            if (SingleKeyPress(Keys.S))
            {
                if (selectedItem is Tower)
                {
                    hud.Money += ((Tower)selectedItem).SellCost();
                    ((Tower)selectedItem).OccupiedTile.OccupiedBy = null;
                    towers.Remove((Tower)selectedItem);
                }
                selectedItem = null;
            }
            if (SingleKeyPress(Keys.U))
            {
                if (selectedItem is Tower)
                {
                    if ((((Tower)selectedItem).UpgradeLevel < 3) && hud.CanSpendMoney(((Tower)selectedItem).Cost))
                    {
                        hud.Money -= ((Tower)selectedItem).SellCost();
                        ((Tower)selectedItem).UpgradeLevel++;
                        ((Tower)selectedItem).Speed -= (float)50;
                        ((Tower)selectedItem).Damage += 1;
                        ((Tower)selectedItem).FireRadius += (float)30;
                        ((Tower)selectedItem).Cost += ((Tower)selectedItem).Cost;
                    }
                }
            }
            if (SingleKeyPress(Keys.A))
            {
                if ((selectedItem is Tower) && !(selectedItem is Tower_Shock))
                {
                    Tower.Attacktype type = ((Tower)selectedItem).AttackType + 1;
                    if ((int)type >= Enum.GetNames(typeof(Tower.Attacktype)).Length)
                        type = Tower.Attacktype.None;
                    ((Tower)selectedItem).AttackType = type;
                }
            }
            if (SingleKeyPress(Keys.Escape))
            {
                gameState = GameState.Menu;
            }
        }
        #endregion Quick Keys

        #region Single Press / Click
        /// <summary> Processes a singular mouse click </summary>
        /// <returns>If the current button press is the same as the last</returns>
        public bool SingleMouseClick()
        {
            if (!singlePress && (mouseState.LeftButton == ButtonState.Released) && (previousMouseState.LeftButton == ButtonState.Pressed))
            {
                singlePress = true;
                return true;
            }
            return false;
        }

        /// <summary> Processes a singular key input. </summary>
        /// <param name="key">The Key you wish to check</param>
        /// <returns>If the current key press is the same as the last</returns>
        public bool SingleKeyPress(Keys key)
        {
            if (kbState.IsKeyUp(key) && previouskbState.IsKeyDown(key))
            {
                return true;
            }
            return false;
        }
        #endregion Single Press / Click

        #region CheckIfClicked (Includes SinglePress)
        /// <summary> Checks if your mouse has clicked a specific Rectangle AND if it's a SingleClick(). </summary>
        /// <param name="area">The area being checked</param>
        /// <returns>If clicked</returns>
        public bool CheckIfClicked(Rectangle area)
        {
            if (area.Intersects(mouseRect))
            {
                if (SingleMouseClick())
                    return true;
            }
            return false;
        }

        /// <summary> Checks if your mouse has clicked a specific Rectangle AND if it's a SingleClick(). </summary>
        /// <param name="area">The object being checked</param>
        /// <returns>If clicked</returns>
        public bool CheckIfClicked(GameObject go)
        {
            return CheckIfClicked(go.Rectangle);
        }
        #endregion CheckIfClicked (Includes SinglePress)

        #endregion QuickKeys / Mouse / Keyboard Stuff

        #region NextLevel-Wave / New-Continue Game

        #region New / Continued Game
        private void SetUpGame()
        {
            gameState = GameState.Game;
            Var.GAME_SPEED = 1;
            difficulty = 1f;
            heldItem = null;
            pausedTime = TimeSpan.Zero;
            animationTotalTime = new GameTime(TimeSpan.Zero, TimeSpan.Zero);
            enemies = new List<Enemy>();
            towers = new List<Tower>();
            traps = new List<Trap>();
            paths = new List<Path>();
            waves = new List<Queue<Enemy>>();
            prevWaves = new List<List<Enemy>>();
            spawnTimer = new Timer(Var.GAME_SPEED);
            droppedCake = new List<Vector2>();
            cakeSelect = new Random();
        }

        public void SetCakePos()
        {
            //Set correct cake positions
            #region Cake Positioning
            switch (level)
            {
                //Level 0 cake position
                case 0:
                    cake.X = Var.GAME_AREA.Left + (Var.TILE_SIZE * 15);
                    cake.Y = Var.GAME_AREA.Top + (Var.TILE_SIZE * 2);
                    break;
                //Level 1 cake position
                case 1:
                    cake.X = Var.GAME_AREA.Left + (Var.TILE_SIZE * 15);
                    cake.Y = Var.GAME_AREA.Top + (Var.TILE_SIZE * 7);
                    break;
                //Level 2 cake position
                case 2:
                    cake.X = Var.GAME_AREA.Left + (Var.TILE_SIZE * 16);
                    cake.Y = Var.GAME_AREA.Top + (Var.TILE_SIZE * 6);
                    break;
                //Boss level cake position
                case 3:
                    cake.X = Var.GAME_AREA.Left + (Var.TILE_SIZE * 15);
                    cake.Y = Var.GAME_AREA.Top + (Var.TILE_SIZE * 2);
                    break;
            }
            #endregion Cake Positioning
        }

        public void NewGame()
        {
            SetUpGame();

            SetUpSelection(Var.START_MONEY, Var.MAX_CAKE_HEALTH);

            level = 0;
            wave = 0;

            SetCakePos();

            randomCakeVar = cakeSelect.Next(0, Var.MAX_CAKE);

            map = new Map(level, spriteBatch);
            if (map.Tiles != null)
            { // Note: This check is also in Load()
                foreach (Tile tile in map.Tiles)
                {
                    if (tile.Rectangle.Intersects(cake.Rectangle))
                        tile.OccupiedBy = cake;
                }
            }

            if (map.Tiles != null)
            {
                switch(level)
                {
                    //Level 1
                    case 0:
                        paths.Add(map.FindPath(map.Tiles[1, 13], map.Tiles[23, 17], 1));
                        break;
                    //Level 2
                    case 1:
                        paths.Add(map.FindPath(map.Tiles[1, 1], map.Tiles[27, 1], 1));
                        break;
                    //Level 3
                    case 2:
                        paths.Add(map.FindPath(map.Tiles[1, 15], map.Tiles[29, 10], 1));
                        break;
                    //Boss level
                    case 3:
                        paths.Add(map.FindPath(map.Tiles[1, 15], map.Tiles[23, 17], 1));
                        break;
                }
            }

            //Gets enemies
            LoadWaves(level, wave);
        }

        public void ContinueGame()
        {
            SetUpGame();
            bool fileLoaded = LoadFile();
            if (!fileLoaded)
            {
                NewGame();
                return;
            }

            // HUD / Cake / Map declared in LoadGame()

            if (map.Tiles != null)
            {
                switch (level)
                {
                    case 0:
                        paths.Add(map.FindPath(map.Tiles[1, 13], map.Tiles[23, 17], 1));
                        break;
                    case 1:
                        paths.Add(map.FindPath(map.Tiles[1, 1], map.Tiles[27, 1], 1));
                        break;
                    case 2:
                        paths.Add(map.FindPath(map.Tiles[1, 1], map.Tiles[27, 1], 1));
                        break;
                }
            }

            // Gets enemies
            LoadWaves(level, wave); // level / wave taken from LoadGame();
        }

        public void SetUpSelection(int money, int cakeLeft)
        {
            // This automatically adds any tower/trap to the selection list.
            List<GameObject> selectionList = new List<GameObject>();
            for (int i = 0; i < Enum.GetNames(typeof(Var.TowerType)).Length; i++)
                selectionList.Add(LoadTower((Var.TowerType)i));
            for (int i = 0; i < Enum.GetNames(typeof(Var.TrapType)).Length; i++)
                selectionList.Add(LoadTrap((Var.TrapType)i));

            cake = new Cake(new ImageObject(cakesTex, 0, 0, Var.TILE_SIZE * 3, Var.TILE_SIZE * 3, spriteBatch), cakeLeft, normalFont);
            hud = new HUD(spriteBatch, money, infoBoxTex, mediumFont, cake, selectionList, menuiTex, this);
            hud.MenuButton.Texture = infoBoxTex;

            hud.InfoWindow = new Window(0, 0, 0, 0, spriteBatch, Var.BLANK_TEX, null, new List<TextObject> { new TextObject("", Vector2.Zero, normalFont, Color.GhostWhite, spriteBatch) });
            hud.InfoWindow.Color = Var.PAUSE_GRAY;

            List<TextObject> texts = new List<TextObject>
            {
                new TextObject("-", Vector2.Zero, normalFont, Color.GhostWhite, spriteBatch),
                new TextObject("-", Vector2.Zero, normalFont, Color.GhostWhite, spriteBatch),
                new TextObject("-", Vector2.Zero, normalFont, Color.GhostWhite, spriteBatch)
            };

            hud.CostWindow = new Window(0, (int)(hud.SelectionBar[0].Y - texts[0].Height - texts[1].Height - texts[2].Height - 10), 100, texts[0].Height + texts[1].Height + texts[2].Height, spriteBatch, Var.BLANK_TEX, null, texts);
            hud.CostWindow.TextObjects[0].Y = hud.CostWindow.Y;
            hud.CostWindow.TextObjects[1].Y = hud.CostWindow.Y + texts[0].Height;
            hud.CostWindow.TextObjects[2].Y = hud.CostWindow.Y + texts[0].Height + texts[0].Height;
            hud.CostWindow.Color = Var.PAUSE_GRAY;
        }
        #endregion New / Continued Game

        #region Next Wave / Level
        public void NextWave()
        {
            spawnTimer.Update(animationTotalTime, Var.GAME_SPEED);

            if ((waves.Count > 0) && (waves[0].Count > 0) && spawnTimer.Finished)
            {
                enemies.Add(waves[0].Dequeue());
                enemies.Last().Start(animationTotalTime);

                if (waves[0].Count > 0)
                    spawnTimer.Start(animationTotalTime, Var.TIME_BETWEEN_SPAWNS);
                else
                    spawnTimer.Start(animationTotalTime, Var.TIME_BETWEEN_WAVES);
            }
            if ((waves.Count > 1) && (waves[0].Count == 0) && spawnTimer.Finished)
            {
                waves.RemoveAt(0);
                wave++;
                hud.CurrentWave = wave;
                prevWaves.Add(waves[0].ToList());
            }

            if ((waves.Count == 1) && (waves[0].Count == 0) && (enemies.Count == 0))
            {
                waves.Clear();
                wave = 0;
                NextLevel();
            }
            else if (prevWaves.Count >= 1)
            {
                bool waveAlive = false;
                foreach (Enemy enemy in prevWaves[0])
                {
                    if (enemy.IsActive && (enemy.Behavior == Enemy.BehaviorState.Spawn))
                    {
                        if (enemy is Enemy_Ant)
                            waveAlive = true;
                        else if (enemy is Enemy_Bee)
                            waveAlive = true;
                        else if (enemy is Enemy_Beetle)
                            waveAlive = true;
                        else if (enemy is Enemy_Dragonfly)
                            waveAlive = true;
                        else if (enemy is Enemy_Ladybug)
                            waveAlive = true;
                        else if (enemy is Enemy_Spider)
                            waveAlive = true;
                        else if (enemy is Enemy_SpiderBoss)
                            waveAlive = true;
                        else if (enemy is Enemy_Wasp)
                            waveAlive = true;
                    }
                }
                if (!waveAlive)
                {
                    prevWaves.RemoveAt(0);
                    SaveFile();
                }
            }
        }

        public void NextLevel()
        {
            level++;
            wave = 0;
            LoadWaves(level, wave);

            SetCakePos();
            randomCakeVar = cakeSelect.Next(0, Var.MAX_CAKE);

            if (waves.Count == 0)
            {
                gameState = GameState.GameOver_Win;
                DeleteSave();
            }
        }
        #endregion Next Wave / Level

        #endregion NextLevel-Wave / New-Continue Game

        #region File Stuff

        #region Load Waves
        /// <summary> Loads wave data from a .lvl file. </summary>
        /// <param name="level">default = 0</param>
        /// <param name="waveNum">default = 0</param>
        private void LoadWaves(int level, int waveNum)
        {
            int wave = waveNum;
            string[] infoArray = null;
            string firstLine = null;

            while (File.Exists("Game Levels/Level" + level + "/wave" + wave + ".lvl"))
            {
                Queue<Enemy> thisWave = new Queue<Enemy>();
                StreamReader reader = new StreamReader("Game Levels/Level" + level + "/wave" + wave + ".lvl");
                infoArray = null;
                firstLine = null;
                while ((firstLine = reader.ReadLine()) != null)
                {
                    // 0-Type || 1-PathType || 2-Number of enemies to enqueue
                    if (firstLine.Contains("//"))
                        firstLine.Remove(firstLine.IndexOf("//"));
                    infoArray = firstLine.Split('-');

                    int numEnemies = Int32.Parse(infoArray[2]);
                    for (int i = 0; i < numEnemies; i++)
                    {
                        thisWave.Enqueue(
                            NewEnemy((Var.EnemyType)Enum.Parse(typeof(Var.EnemyType), infoArray[0], true), paths[Int32.Parse(infoArray[1])])
                        );
                    }
                }
                if (thisWave.Count > 0)
                    waves.Add(thisWave);
                wave++;
                difficulty += Var.WAVES_DIFFICULTY_INCREASE;
            }
            if (hud != null)
            {
                hud.MaxWave = waves.Count;
                hud.CurrentWave = waveNum;
            }
            wave = waveNum;
            if (waves.Count > 0)
                prevWaves.Add(waves[0].ToList());
        }
        #endregion Load Waves

        #region Load
        /// <summary> Loads Game info such as money, cake, level, wave, saved towers, and saved traps. also MAP is created here. </summary>
        public bool LoadFile()
        {
            if (CheckForSave())
            {
                StreamReader reader = new StreamReader("Save.sav");
                string[] infoArray = null;
                string firstLine = null;
                if ((firstLine = reader.ReadLine()) != null)
                {
                    if (firstLine.Contains("//"))
                        firstLine = firstLine.Remove(firstLine.IndexOf("//"));

                    // 0-Money ||| 1-CakeLeft ||| 2-Level ||| 3-Wave
                    infoArray = firstLine.Split('-');

                    SetUpSelection(Int32.Parse(infoArray[0]), Int32.Parse(infoArray[1]));
                    level = Int32.Parse(infoArray[2]);
                    wave = Int32.Parse(infoArray[3]);

                    // Map is declared here as you need the map to place towers and traps, but you need what level to load.
                    map = new Map(level, spriteBatch);
                    if (map.Tiles != null)
                    { // Note: This check is also in NewGame()
                        foreach (Tile tile in map.Tiles)
                        {
                            if (tile.Rectangle.Intersects(cake.Rectangle))
                                tile.OccupiedBy = cake;
                        }
                    }

                    if (map.Tiles != null)
                    {
                        string curType = reader.ReadLine();
                        Tower tempTower; string[] coord;
                        while (curType == "--Towers--")
                        {
                            firstLine = reader.ReadLine();
                            if (firstLine == null || (firstLine[0] == '-' && firstLine[1] == '-'))
                            {
                                curType = firstLine;
                                break;
                            }
                            if (firstLine.Contains("//"))
                                firstLine = firstLine.Remove(firstLine.IndexOf("//"));

                            // 0-Type ||| 1-tile (x,y) ||| 2-health ||| 3-AttackType
                            infoArray = firstLine.Split('-'); coord = infoArray[1].Split(',');
                            tempTower = LoadTower((Var.TowerType)Enum.Parse(typeof(Var.TowerType), infoArray[0], true));
                            tempTower.Place((Tile_Tower)map.Tiles[Int32.Parse(coord[0]), Int32.Parse(coord[1])]);
                            towers.Add(tempTower);
                        }

                        Trap tempTrap;
                        while (curType == "--Traps--")
                        {
                            firstLine = reader.ReadLine();
                            if (firstLine == null || (firstLine[0] == '-' && firstLine[1] == '-'))
                            {
                                curType = firstLine;
                                break;
                            }
                            if (firstLine.Contains("//"))
                                firstLine = firstLine.Remove(firstLine.IndexOf("//"));

                            // 0-Type ||| 1-tile (x,y) ||| 2-health
                            infoArray = firstLine.Split('-'); coord = infoArray[1].Split(',');
                            tempTrap = LoadTrap((Var.TrapType)Enum.Parse(typeof(Var.TrapType), infoArray[0], true));
                            tempTrap.Place((Tile_Path)map.Tiles[Int32.Parse(coord[0]), Int32.Parse(coord[1])]);
                            traps.Add(tempTrap);
                        }
                    }
                }
                else
                {
                    reader.Close();
                    reader.Dispose();
                    return false;
                }
                reader.Close();
                reader.Dispose();
                return true;
            }
            return false;
        }
        #endregion Load

        #region Save
        public void SaveFile()
        {
            StreamWriter writer = new StreamWriter("Save.sav");
            // 0-Money ||| 1-CakeLeft ||| 2-Level ||| 3-Wave
            writer.WriteLine(hud.Money + "-" + cake.CurrentHealth + "-" + level + "-" + wave + "// 0-Money ||| 1-CakeLeft ||| 2-Level ||| 3-Wave");

            // 0-Type ||| 1-tile (x,y) ||| 2-health ||| 3-AttackType
            writer.WriteLine("--Towers--");
            towers.ForEach(tower => writer.WriteLine(tower.Type + "-" + (tower.OccupiedTile.TileNum.X + "," + tower.OccupiedTile.TileNum.Y) + "-" + tower.CurrentHealth + "-" + tower.AttackType));

            // 0-Type ||| 1-tile (x,y) ||| 2-health
            writer.WriteLine("--Traps--");
            traps.ForEach(trap => writer.WriteLine(trap.Type + "-" + (trap.OccupiedTile.TileNum.X + "," + trap.OccupiedTile.TileNum.Y) + "-" + trap.CurrentHealth));
            writer.Close();
            writer.Dispose();

            hud.GameSaved();
        }
        #endregion Save

        #region Check If Saved Game / Delete Save
        public bool CheckForSave()
        {
            if (File.Exists("save.sav"))
            {
                StreamReader reader = new StreamReader("save.sav");
                string line;
                if ((line = reader.ReadLine()) != null && line != "")
                {
                    reader.Close();
                    reader.Dispose();
                    return true;
                }
                reader.Close();
                reader.Dispose();
            }
            return false;
        }

        public void DeleteSave()
        {
            StreamWriter writer = new StreamWriter("Save.sav");
            writer.Write("");
            writer.Close();
            writer.Dispose();
        }
        #endregion Check If Saved Game / Delete Save

        #endregion File Stuff

        #region New Enemy / Tower / Trap

        #region Enemy
        private Enemy NewEnemy(Var.EnemyType type, Path path)
        {
            ImageObject image;

            ImageObject effects = new ImageObject(enemy_effects, 0, 0, Var.ENEMY_SIZE, Var.ENEMY_SIZE, 4, 0, 0, Var.ENEMY_SIZE, Var.ENEMY_SIZE, 0, 0, Color.White, 100f, ImageObject.UP, Vector2.Zero, SpriteEffects.None, spriteBatch);
            effects.CenterOrigin();

            switch(type)
            {
                //Ants are fast, but have a much smaller health pool than other units
                #region Ant
                case Var.EnemyType.Ant:
                    image = new ImageObject(ant, 0, 0, Var.ENEMY_SIZE, Var.ENEMY_SIZE, 4, 0, 0, Var.ENEMY_SIZE, Var.ENEMY_SIZE, 0, 0, Color.White, 100f, ImageObject.RIGHT, Vector2.Zero, SpriteEffects.None, spriteBatch);
                    image.CenterOrigin();
                    return new Enemy_Ant
                    (
                        image,
                        effects,
                        (int)(Var.ANT_HEALTH * difficulty),
                        (int)(Var.ANT_DAMAGE * difficulty),
                        Var.ANT_SPEED * difficulty,
                        path,
                        cake,
                        hud
                    );
                #endregion Ant

                //Spiders are "standard" units -- average stats
                #region Spider
                case Var.EnemyType.Spider:
                    image = new ImageObject(spider, 0, 0, Var.ENEMY_SIZE, Var.ENEMY_SIZE, 4, 0, 0, Var.ENEMY_SIZE, Var.ENEMY_SIZE, 0, 0, Color.White, 100f, ImageObject.RIGHT, Vector2.Zero, SpriteEffects.None, spriteBatch);
                    image.CenterOrigin();
                    return new Enemy_Spider
                    (
                        image,
                        effects,
                        (int)(Var.SPIDER_HEALTH * difficulty),
                        (int)(Var.SPIDER_DAMAGE * difficulty),
                        Var.SPIDER_SPEED * difficulty,
                        path,
                        cake,
                        hud
                    );
                #endregion Spider

                //Beetles are tanks -- slower move speed, but a much greater health pool
                #region Beetle
                case Var.EnemyType.Beetle:
                    image = new ImageObject(beetle, 0, 0, Var.ENEMY_SIZE, Var.ENEMY_SIZE, 4, 0, 0, Var.ENEMY_SIZE, Var.ENEMY_SIZE, 0, 0, Color.White, 100f, ImageObject.RIGHT, Vector2.Zero, SpriteEffects.None, spriteBatch);
                    image.CenterOrigin();
                    return new Enemy_Beetle
                    (
                        image,
                        effects,
                        (int)(Var.BEETLE_HEALTH * difficulty),
                        (int)(Var.BEETLE_DAMAGE * difficulty),
                        Var.BEETLE_SPEED * difficulty,
                        path,
                        cake,
                        hud
                    );
                #endregion Beetle

                //Bees attack towers, but damage themselves in the attack
                #region Bee
                case Var.EnemyType.Bee:
                    image = new ImageObject(bee, 0, 0, Var.ENEMY_SIZE, Var.ENEMY_SIZE, 4, 0, 0, Var.ENEMY_SIZE, Var.ENEMY_SIZE, 0, 0, Color.White, 100f, ImageObject.RIGHT, Vector2.Zero, SpriteEffects.None, spriteBatch);
                    image.CenterOrigin();
                    return new Enemy_Bee
                    (
                        image,
                        effects,
                        (int)(Var.BEE_HEALTH * difficulty),
                        (int)(Var.BEE_DAMAGE * difficulty),
                        Var.BEE_SPEED * difficulty,
                        path,
                        cake,
                        hud
                    );
                #endregion Bee

                //Wasps attack towers until dealt with
                #region Wasp
                case Var.EnemyType.Wasp:
                    image = new ImageObject(wasp, 0, 0, Var.ENEMY_SIZE, Var.ENEMY_SIZE, 4, 0, 0, Var.ENEMY_SIZE, Var.ENEMY_SIZE, 0, 0, Color.White, 100f, ImageObject.RIGHT, Vector2.Zero, SpriteEffects.None, spriteBatch);
                    image.CenterOrigin();
                    return new Enemy_Wasp
                    (
                        image,
                        effects,
                        (int)(Var.WASP_HEALTH * difficulty),
                        (int)(Var.WASP_DAMAGE * difficulty),
                        Var.WASP_SPEED * difficulty,
                        path,
                        cake,
                        hud
                    );
                #endregion Wasp

                //Dragonflies attack traps
                #region Dragonflies
                case Var.EnemyType.Dragonfly:
                    image = new ImageObject(dragonfly, 0, Var.ENEMY_SIZE, Var.ENEMY_SIZE, Var.ENEMY_SIZE, 4, 0, Var.ENEMY_SIZE, Var.ENEMY_SIZE, Var.ENEMY_SIZE, 0, 0, Color.White, 100f, ImageObject.RIGHT, Vector2.Zero, SpriteEffects.None, spriteBatch);
                    image.CenterOrigin();
                    return new Enemy_Wasp
                    (
                        image,
                        effects,
                        (int)(Var.DRAGONFLY_HEALTH * difficulty),
                        (int)(Var.DRAGONFLY_DAMAGE * difficulty),
                        Var.DRAGONFLY_SPEED * difficulty,
                        path,
                        cake,
                        hud
                    );
                #endregion Wasp

                //Ladybugs heal allies, but deal no damage
                #region Ladybug
                case Var.EnemyType.Ladybug:
                    image = new ImageObject(ladybug, 0, Var.ENEMY_SIZE, Var.ENEMY_SIZE, Var.ENEMY_SIZE, 4, 0, Var.ENEMY_SIZE, Var.ENEMY_SIZE, Var.ENEMY_SIZE, 0, 0, Color.White, 100f, ImageObject.RIGHT, Vector2.Zero, SpriteEffects.None, spriteBatch);
                    image.CenterOrigin();
                    return new Enemy_Ladybug
                    (
                        image,
                        effects,
                        (int)(Var.LADYBUG_HEALTH * difficulty),
                        (int)(Var.LADYBUG_DAMAGE * difficulty),
                        Var.LADYBUG_SPEED * difficulty,
                        path,
                        cake,
                        hud
                    );
                #endregion Ladybug

                //Spider Boss
                #region Spider Boss
                case Var.EnemyType.SpiderBoss:
                    image = new ImageObject(boss, 0, 0, Var.BOSS_SIZE, Var.BOSS_SIZE, 4, 0, 0, Var.BOSS_SIZE, Var.BOSS_SIZE, 0, 0, Color.White, 100f, ImageObject.RIGHT, Vector2.Zero, SpriteEffects.None, spriteBatch);
                    image.CenterOrigin();
                    return new Enemy_SpiderBoss
                    (
                        image,
                        effects,
                        (int)(Var.BOSS_HEALTH * difficulty),
                        (int)(Var.BOSS_DAMAGE * difficulty),
                        Var.BOSS_SPEED * difficulty,
                        path,
                        cake,
                        hud
                    );
                #endregion Spider Boss

                default:
                    return null;
            }
        }
        #endregion Enemy

        #region Tower
        private Tower LoadTower(Var.TowerType type)
        {
            ImageObject image;
            switch (type)
            {
                //Rad towers are standard towers that shoot at enemies
                #region Rad
                case Var.TowerType.Rad:
                    image = new ImageObject(towersTex, 0, 0, Var.TOWER_SIZE, Var.TOWER_SIZE, 4, 0, 0, Var.TOWER_SIZE, Var.TOWER_SIZE, 0, 0, Color.White, 100f, ImageObject.UP, Vector2.Zero, SpriteEffects.None, spriteBatch);
                    image.CenterOrigin();
                    return new Tower_Rad(
                        image,
                        150f,
                        Var.RAD_TOWER_HEALTH,
                        125,
                        1,
                        500,//Fire rate in ms
                        Var.BASE_BULLET_SPEED,
                        ammoTex,
                        Tower.Attacktype.None,
                        towerShoot
                    );
                #endregion Rad
                
                //Shock towers cause area damage over time
                #region Shock
                case Var.TowerType.Shock:
                    image = new ImageObject(towersTex, 0, 0, Var.TOWER_SIZE, Var.TOWER_SIZE, 4, 0, 40, Var.TOWER_SIZE, Var.TOWER_SIZE, 0, 0, Color.White, 100f, ImageObject.UP, Vector2.Zero, SpriteEffects.None, spriteBatch);
                    image.CenterOrigin();
                    return new Tower_Shock(
                        image,
                        150f,
                        Var.SHOCK_TOWER_HEALTH,
                        500,
                        1,
                        750,//Fire rate in ms
                        Var.BASE_BULLET_SPEED,
                        ammoTex,
                        Tower.Attacktype.None
                    );
                #endregion Shock

                //Fire towers are much stronger versions of Rad towers
                #region Fire
                case Var.TowerType.Fire:
                    image = new ImageObject(towersTex, 0, 0, Var.TOWER_SIZE, Var.TOWER_SIZE, 4, 0, 80, Var.TOWER_SIZE, Var.TOWER_SIZE, 0, 0, Color.White, 100f, ImageObject.UP, Vector2.Zero, SpriteEffects.None, spriteBatch);
                    image.CenterOrigin();
                    return new Tower_Fire(
                        image,
                        150f,
                        Var.FIREBALL_TOWER_HEALTH,
                        200,
                        4,
                        850,//Fire rate in ms
                        Var.BASE_BULLET_SPEED,
                        ammoTex,
                        Tower.Attacktype.None,
                        fireball
                    );
                #endregion Fire

                //Light towers attract bugs away from cake and other towers
                #region Light
                case Var.TowerType.Light:
                    image = new ImageObject(towersTex, 0, 0, Var.TOWER_SIZE, Var.TOWER_SIZE, 4, 0, 120, Var.TOWER_SIZE, Var.TOWER_SIZE, 0, 0, Color.White, 100f, ImageObject.UP, Vector2.Zero, SpriteEffects.None, spriteBatch);
                    image.CenterOrigin();
                    return new Tower_Light(
                        image,
                        150f,
                        Var.LIGHT_TOWER_HEALTH,
                        500,
                        1,
                        750,//Fire rate in ms
                        Var.BASE_BULLET_SPEED,
                        ammoTex,
                        Tower.Attacktype.None
                    );
                #endregion Light

                default:
                    return null;
            }
        }
        #endregion Tower

        #region Trap
        private Trap LoadTrap(Var.TrapType type)
        {
            ImageObject image;
            switch(type)
            {
                //Acid traps are standard traps that cause damage to enemies
                #region Acid
                case Var.TrapType.Acid:
                    image = new ImageObject(trapsTex, 0, 0, Var.TRAP_SIZE, Var.TRAP_SIZE, 4, 0, Var.TRAP_SIZE, Var.TRAP_SIZE, Var.TRAP_SIZE, 0, 0, Color.White, 100f, ImageObject.UP, Vector2.Zero, SpriteEffects.None, spriteBatch);
                    image.CenterOrigin();
                    return new Trap_Acid
                    (
                        image,
                        Var.ACID_TRAP_HEALTH,
                        5,
                        50
                    );
                #endregion Acid

                //Flypaper traps decrease enemy speed by a set increment for a period of time
                #region Flypaper
                case Var.TrapType.Flypaper:
                    image = new ImageObject(trapsTex, 0, 0, Var.TRAP_SIZE, Var.TRAP_SIZE, 4, 0, Var.TRAP_SIZE * 2, Var.TRAP_SIZE, Var.TRAP_SIZE, 0, 0, Color.White, 100f, ImageObject.UP, Vector2.Zero, SpriteEffects.None, spriteBatch);
                    image.CenterOrigin();
                    return new Trap_Flypaper
                    (
                        image,
                        Var.FLYPAPER_TRAP_HEALTH,
                        6,
                        25
                    );
                #endregion Flypaper

                //Zapper traps deal a great deal of damage to enemies, but have a short life
                #region Zapper
                case Var.TrapType.Zapper:
                    //change to animated zapper tex, bbro
                    image = new ImageObject(trapsTex, 0, 0, Var.TRAP_SIZE, Var.TRAP_SIZE, 4, 0, Var.TRAP_SIZE * 3, Var.TRAP_SIZE, Var.TRAP_SIZE, 0, 0, Color.White, 100f, ImageObject.UP, Vector2.Zero, SpriteEffects.None, spriteBatch);
                    image.CenterOrigin();
                    return new Trap_Zapper(
                        image,
                        Var.ZAPPER_TRAP_HEALTH,
                        1,
                        150
                    );
                #endregion Zapper

                //Snare traps don't deal damage to enemies, but instead take back a single piece of cake per snare
                #region Snare
                case Var.TrapType.Snare:
                    image = new ImageObject(trapsTex, 0, 0, Var.TRAP_SIZE, Var.TRAP_SIZE, 4, 0, Var.TRAP_SIZE * 4, Var.TRAP_SIZE, Var.TRAP_SIZE, 0, 0, Color.White, 100f, ImageObject.UP, Vector2.Zero, SpriteEffects.None, spriteBatch);
                    image.CenterOrigin();
                    return new Trap_Snare
                    (
                        image,
                        Var.SNARE_TRAP_HEALTH,
                        0,
                        225
                    );
                #endregion Snare

                default:
                    return null;
            }
        }
        #endregion Trap

        #endregion New Enemy / Tower / Trap

        #region Button Event Methods
        public void SwitchPauseAndGame(Button bttn)
        {
            if (gameState == GameState.Game)
                gameState = GameState.Paused;
            else
                gameState = GameState.Game;
        }

        public void Mute_UnMute(Button bttn)
        {
            soundEffectsOn = musicOn = !musicOn;
        }

        public void GoToMenu(Button bttn)
        {
            gameState = GameState.Menu;
        }

        public void RestartGame(Button bttn)
        {
            NewGame();
        }

        #region Game Speed Buttons
        public void GameSpeedOne(Button bttn)
        {
            GameSpeedChange(1, bttn);
        }

        public void GameSpeedTwo(Button bttn)
        {
            GameSpeedChange(2, bttn);
        }

        public void GameSpeedFour(Button bttn)
        {
            GameSpeedChange(4, bttn);
        }

        private void GameSpeedChange(int speed, Button bttn)
        {
            Var.GAME_SPEED = speed;
            hud.MenuButton.ChildButtons[1].ChildButtons.ForEach(button => button.Message.Color = Color.Red);
            bttn.Message.Color = Color.Maroon;
        }
        #endregion Game Speed Buttons

        #endregion Button Event Methods

        #region Other

        #region Dropdown Menu
        public void ClickGameDropDownMenuItemsIfCan()
        {
            if (hud.MenuButton.Focused)
            {
                List<Button> tempList = new List<Button>();
                tempList.AddRange(hud.MenuButton.ChildButtons[1].ChildButtons);
                tempList.AddRange(hud.MenuButton.ChildButtons);

                foreach (Button bttn in tempList)
                {
                    if (CheckIfClicked(bttn.Rectangle))
                        bttn.Click();
                }
            }
        }
        #endregion Dropdown Menu

        #region Draw Circle
        // NOTE: this code taken from MessiahAndrw at http://forums.create.msdn.com/forums/t/7414.aspx (and then modified some =p)

        /// <summary>
        /// Creates a circle starting from 0, 0.
        /// </summary>
        /// <param name="radius">The radius (half the width) of the circle.</param>
        /// <param name="sides">The number of sides on the circle (the more the detailed).</param>
        public void DrawCircle(Vector2 cCenter, float radius, int sides, Color color)
        {
            List<Vector2> vectors = new List<Vector2>();

            float max = 2 * (float)Math.PI;
            float step = max / (float)sides;

            for (float theta = 0; theta < max; theta += step)
            {
                vectors.Add(new Vector2(cCenter.X + radius * (float)Math.Cos((double)theta),
                    cCenter.Y + radius * (float)Math.Sin((double)theta)));
            }

            // then add the first vector again so it's a complete loop
            vectors.Add(vectors.First());

            RenderCircle(vectors, color);
        }

        /// <summary>
        /// Renders the primtive line object.
        /// </summary>
        /// <param name="spriteBatch">The sprite batch to use to render the primitive line object.</param>
        public void RenderCircle(List<Vector2> vectors, Color color)
        {
            if (vectors.Count < 2)
                return;

            Vector2 start, end, scale;
            int lineWidth = 3;
            float rotation;

            for (int i = 1; i <= vectors.Count; i++)
            {
                start = vectors[i - 1];
                if (i == vectors.Count)
                    end = vectors[0];
                else
                    end = vectors[i];

                scale = new Vector2(Vector2.Distance(end, start), lineWidth);

                // Calculate the rotation
                rotation = (float)Math.Atan2(end.Y - start.Y, end.X - start.X);

                // Draw
                spriteBatch.Draw(pixel, start, null, color, rotation, Vector2.Zero, scale, SpriteEffects.None, 0.0f);
            }
        }
        #endregion Draw Circle

        #endregion Other
    }
}